package com.tanhua.manager.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manager.domain.AnalysisByDay;
import com.tanhua.manager.mapper.AnalysisMapper;
import com.tanhua.manager.mapper.LogMapper;
import com.tanhua.manager.utils.ComputeUtil;
import com.tanhua.manager.vo.AnalysisChartDataItem;
import com.tanhua.manager.vo.AnalysisChartDataVO;
import com.tanhua.manager.vo.AnalysisSummaryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author liuyp
 * @date 2021/02/21
 */
@Service
public class AnalysisService extends ServiceImpl<AnalysisMapper, AnalysisByDay> {

    @Autowired
    private LogMapper logMapper;

    /**
     * 首页-概要信息统计
     */
    public ResponseEntity summary() {
        AnalysisSummaryVO vo = new AnalysisSummaryVO();

        //cumulativeUsers 累计用户
        Long cumulativeUsers = this.baseMapper.cumulativeUsers();
        vo.setCumulativeUsers(cumulativeUsers);

        //activePassMonth 过去30天活跃用户数（使用的是hutool的DateUtil工具进行日期偏移计算）
        Date now = new Date();
        String today = DateUtil.format(now, "yyyy-MM-dd");
        String date30 = DateUtil.offsetDay(now, -30).toString("yyyy-MM-dd");
        Long activePassMonth = this.baseMapper.activeUsersByRangeDate(date30, today);
        vo.setActivePassMonth(activePassMonth);

        //activePassWeek 过去7天活跃用户数
        String date7 = DateUtil.offsetDay(now, -7).toString("yyyy-MM-dd");
        Long activePassWeek = this.baseMapper.activeUsersByRangeDate(date7, today);
        vo.setActivePassWeek(activePassWeek);

        //newUsersToday 今日新增用户
        AnalysisByDay analysisToday = query().eq("record_date", today).one();
        Integer newUsersToday = analysisToday.getNumRegistered();
        vo.setNewUsersToday(newUsersToday.longValue());

        //newUsersTodayRate 今日新增用户的涨跌率。跟昨天对比的涨跌率
        String yesterday = DateUtil.offsetDay(now, -1).toString("yyyy-MM-dd");
        AnalysisByDay analysisYesterday = query().eq("record_date", yesterday).one();
        Integer newUsersYesterday = analysisYesterday.getNumRegistered();
        BigDecimal newUsersTodayRate = ComputeUtil.computeRate(newUsersToday.longValue(), newUsersYesterday.longValue());
        vo.setNewUsersTodayRate(newUsersTodayRate);

        //loginTimesToday 今日登录次数
        Integer loginTimesToday = analysisToday.getNumLogin();
        vo.setLoginTimesToday(loginTimesToday.longValue());

        //loginTimesTodayRate 今日登录次数的涨跌率
        Integer loginTimesYesterday = analysisYesterday.getNumLogin();
        BigDecimal loginTimesTodayRate = ComputeUtil.computeRate(loginTimesToday.longValue(), loginTimesYesterday.longValue());
        vo.setLoginTimesTodayRate(loginTimesTodayRate);

        //activeUsersToday 今日活跃用户数
        Integer activeUsersToday = analysisToday.getNumActive();
        vo.setActiveUsersToday(activeUsersToday.longValue());

        //activeUsersTodayRate 今日活跃用户数的涨跌率
        Integer activeUsersYesterday = analysisYesterday.getNumActive();
        BigDecimal activeUsersTodayRate = ComputeUtil.computeRate(activeUsersToday.longValue(), activeUsersYesterday.longValue());
        vo.setActiveUsersTodayRate(activeUsersTodayRate);

        return ResponseEntity.ok(vo);
    }

    /**
     * 首页-折线图数据（新增、活跃用户、次日留存率）
     * @param sd 开始时间，毫秒值
     * @param ed 结束时间，毫秒值
     * @param type 操作类型。101新增，102活跃用户，103次日留存率
     */
    public ResponseEntity usersChartData(Long sd, Long ed, Integer type) {
        AnalysisChartDataVO vo = new AnalysisChartDataVO();

        //1. 今年的数据
        //1.1 准备查询的日期范围
        String startDateThisYear = DateUtil.date(sd).toString("yyyy-MM-dd");
        String endDateThisYear = DateUtil.date(ed).toString("yyyy-MM-dd");
        //1.2 从数据库里查询日期范围内的数据
        List<AnalysisByDay> analysisListThisYear = query().between("record_date", startDateThisYear, endDateThisYear).list();
        //1.3 把每天的数据转换成AnalysisChartDataItem对象
        List<AnalysisChartDataItem> thisYearList = new ArrayList<>();
        for (AnalysisByDay analysis : analysisListThisYear) {
            AnalysisChartDataItem item = new AnalysisChartDataItem();

            item.setTitle(DateUtil.format(analysis.getRecordDate(), "yyyy-MM-dd"));
            if (type == 101) {
                item.setAmount(analysis.getNumRegistered().longValue());
            } else if (type == 102) {
                item.setAmount(analysis.getNumActive().longValue());
            } else if (type == 103) {
                item.setAmount(analysis.getNumRetention1d().longValue());
            }

            thisYearList.add(item);
        }
        //1.4 把今年的AnalysisChartDataItem集合，放到vo的thisYear里
        vo.setThisYear(thisYearList);

        //2. 去年的数据
        //2.1 准备去年的日期范围
        String startDateLastYear = DateUtil.date(sd).offset(DateField.YEAR, -1).toString("yyyy-MM-dd");
        String endDateLastYear = DateUtil.date(ed).offset(DateField.YEAR, -1).toString("yyyy-MM-dd");
        //2.2 从数据库里查询指定范围内的数据
        List<AnalysisByDay> analysisListLastYear = query().between("record_date", startDateLastYear, endDateLastYear).list();
        //2.3 把去年每天的数据，转换成AnalysisChartDataItem对象
        List<AnalysisChartDataItem> lastYearList = new ArrayList<>();
        for (AnalysisByDay analysis : analysisListLastYear) {
            AnalysisChartDataItem item = new AnalysisChartDataItem();

            item.setTitle(DateUtil.format(analysis.getRecordDate(), "yyyy-MM-dd"));
            if (type == 101) {
                item.setAmount(analysis.getNumRegistered().longValue());
            } else if (type == 102) {
                item.setAmount(analysis.getNumActive().longValue());
            } else if (type == 103) {
                item.setAmount(analysis.getNumRetention1d().longValue());
            }

            lastYearList.add(item);
        }
        //2.4 封装到vo里
        vo.setLastYear(lastYearList);

        return ResponseEntity.ok(vo);
    }

    /**
     * 分析日志，把分析结果存储到tb_analysis_by_day表里
     * 需要统计今天的：
     *      1. 新增用户数量（新注册的数量）
     *      2. 活跃用户数量（用户只要登录了、发动态了、评论了、点赞了....，在系统里做任何操作，都是活跃用户）
     *      3. 登录次数
     *      4. 次日留存用户数（昨天注册了，今天活跃）
     */
    public void analysisLog() {
        //1. 获取今天的日期
        Date date = new Date();
        String today = DateUtil.date(date).toDateStr();

        //2. 从数据库里查询今天的数据。如果没有就插入一条
        AnalysisByDay analysis = query().eq("record_date", today).one();
        if (analysis == null) {
            analysis = new AnalysisByDay();
            analysis.setRecordDate(date);
            analysis.setCreated(new Date());
            analysis.setUpdated(new Date());
            save(analysis);
        }

        //3. 统计今天新增的用户数量
        Long newUserCount = logMapper.queryUsersCountByType(today, "0102");
        analysis.setNumRegistered(newUserCount.intValue());

        //4. 统计今天活跃用户数量
        Long activeUserCount = logMapper.queryActiveUserCount(today);
        analysis.setNumActive(activeUserCount.intValue());

        //5. 统计今天登录次数
        Long loginTimes = logMapper.queryUsersCountByType(today, "0101");
        analysis.setNumLogin(loginTimes.intValue());

        //6. 统计留存用户数量
        String yesterday = DateUtil.offsetDay(date, -1).toDateStr();
        Long retentionUserCount = logMapper.queryRetentionUserCount(today, yesterday);
        analysis.setNumRetention1d(retentionUserCount.intValue());

        //7. 把结果更新到数据库里
        updateById(analysis);
    }
}
